package it.uni.bo.monitoring.sla;

import it.uni.bo.monitoring.mapping.hibernate.Sla;
import it.uni.bo.monitoring.protocol.unmarshaller.EventInfo;
import it.uni.bo.monitoring.sla.context.MonitoringComponent;
import it.uni.bo.monitoring.sla.context.MonitoringContext;
import it.uni.bo.monitoring.sla.parser.SlaBean;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;


import org.apache.log4j.Logger;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;

import static it.uni.bo.monitoring.service.StaticFields.QUERY_ALL_SLA;
import static it.uni.bo.monitoring.service.StaticFields.QUERY_SLA2;

public class MonitoringEvent extends Thread {

	private LinkedBlockingQueue<EventInfo> eventData;
	private BlockingQueue<byte[]> rdoToRemove;
	private SessionFactory factory;
	private MonitoringComponent mc;
	private HashMap<Long, MonitoringContext> contextMap;
	private Session session = null;
	private String slaLanguage;
	private Logger l;

	public MonitoringEvent(LinkedBlockingQueue<EventInfo> eventData,
			BlockingQueue<byte[]> rdoToRemove, SessionFactory factory, MonitoringComponent mc, String slaLanguage) {
		l = Logger.getLogger(this.getClass());
		this.eventData=eventData;
		this.rdoToRemove= rdoToRemove;
		this.factory=factory;
		this.mc=mc;
		this.slaLanguage=slaLanguage;
		contextMap=new HashMap<Long, MonitoringContext>();
		int num =0;
		if(factory!=null){
			if((session==null) || (!session.isOpen()))
				session=factory.openSession();
			Query query = session.createQuery(QUERY_ALL_SLA);
			query.setCharacter(0, '0');
			l.info("Hibernate: "+QUERY_ALL_SLA+" --[ '0' ]");
			query.setMaxResults(100);
			Iterator objects = query.iterate();
			if(objects!=null){
				while(objects.hasNext()){
					Object o = objects.next();
					num++;
					if(o instanceof Sla){
						Sla sla = (Sla)o;
						SlaBean sb = SlaBean.getSlaBean(slaLanguage);
						l.info("Parsing SLA..."+ " "+sla.getIdSla()+"");
						sb.parse(sla.getSla());
						contextMap.put(sla.getIdSla(), new MonitoringContext(sb, factory));
					}
				}
			}
			if ((session!=null) && (session.isOpen())) 
				session.close();
		}
		l.info("Sono stati caricati i seguenti SLA"+ " ("+num+")");
	}

	public synchronized void run() {
		ArrayList<byte[]> rdoArray = new ArrayList<byte[]>();
		Session session = null;
		if(factory!=null)
			while(true){
				try {
					rdoArray.clear();
					do{
						EventInfo ei= eventData.take();
						eventData.remove(ei);
						if(ei!=null){
							rdoArray.add(ei.getIdE());
							if((session==null) || (!session.isOpen()))
								session=factory.openSession();
							long idSla=ei.getIdSla();
							if(idSla>=0){
								if(contextMap.containsKey(idSla))
									mc.processEvent(ei, contextMap.get(idSla));
								else{
									Query query = session.createQuery(QUERY_SLA2);
									query.setLong(0, ei.getIdA());
									query.setLong(1, ei.getIdU());
									l.info("Hibernate: "+QUERY_SLA2+" [ "+ei.getIdA()+" "+ei.getIdU()+" ]");
									query.setMaxResults(1);
									Object ob = query.uniqueResult();
									if(ob!=null){
										if(ob instanceof Sla){
											Sla sla = (Sla)ob;
											SlaBean dv = SlaBean.getSlaBean(slaLanguage);
											dv.parse(sla.getSla());
											MonitoringContext context = new MonitoringContext(dv, factory);
											contextMap.put(idSla, context);
											mc.processEvent(ei, context);
										}
									}
								}
								
							}
						}
					}while(eventData.size()>0);
				} catch (InterruptedException e) {
					l.error(e.getMessage());
				}finally{
					if ((session!=null) && (session.isOpen())) 
						session.close();
					//l.info("rimuovo dal Monitorig Eventi"+rdoArray.size());
					rdoToRemove.addAll(rdoArray);
				}
			}

	}
}
